﻿using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using ST.Data;
using ST.ModelVM.ProtocolSimHost;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace ST.Receiver.Tasks
{
    public class TcpConnection : BaseConnection
    {
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        DateTime LstOpenDt = DateTime.MinValue;

        public override bool Open(Data.ProtocolSim mm)
        {
            if ((DateTime.Now - LstOpenDt).TotalSeconds < 5)
            {
                return false;
            }
            LstOpenDt = DateTime.Now;
            if (socket != null)
            {
                socket.Dispose();
            }
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                socket.Connect(new IPEndPoint(IPAddress.Parse(SimWorker.ProtocolSim.IP), mm.Port));
            }
            catch
            {
                 
            }
            var msg = socket.Connected ? "成功" : "失败";
            TransMain.Instance.AddSimLog(SimWorker.Id, 0, "采集器", new byte[] {   }, $"打开{SimWorker.ProtocolSim.Port} {msg}");
            return socket.Connected;
        }

        public override bool Close()
        {
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            socket.Dispose();
            return true;
        }

        public override bool IsOpen()
        {
            return socket.Connected;
        }

        public override int Available()
        {
            if (!socket.Connected)
            {
                return 0;
            }
            return socket.Available;
        }
        byte[] GetSendData(ReqAndRevVM req)
        {
            req.SeqNo++;
            var  data = req.GetSendData();
            var senddata=new byte[data.Length+6];
            senddata[0] = Convert.ToByte(req.SeqNo >> 8);
            senddata[1] = Convert.ToByte(req.SeqNo & 0xff);
            senddata[2] = 0;
            senddata[3] = 0;
            senddata[4] = Convert.ToByte(data.Length >> 8);
            senddata[5] = Convert.ToByte(data.Length & 0xff);
            Buffer.BlockCopy(data, 0, senddata, 6, data.Length);
            return senddata;
        }
        byte[] GetCmdData(ReqAndRevVM req)
        {
            req.SeqNo++;
            var data = req.SendData ;
            var senddata = new byte[data.Length + 6];
            senddata[0] = Convert.ToByte(req.SeqNo >> 8);
            senddata[1] = Convert.ToByte(req.SeqNo & 0xff);
            senddata[2] = 0;
            senddata[3] = 0;
            senddata[4] = Convert.ToByte(data.Length >> 8);
            senddata[5] = Convert.ToByte(data.Length & 0xff);
           
            Buffer.BlockCopy(data, 0, senddata, 6, data.Length);
            return senddata;
        }

        public override  async Task<int> SendAndRev(ProtocolSimHost  mm, ReqAndRevVM req)
        {
            var senddata = GetSendData(req);
            if (socket.Available > 0)
            {
                var datatmp = new byte[socket.Available];
                socket.Receive(datatmp);
            }
            var sendlen = socket.Send(senddata);
            if (sendlen == 0)
            {
                // 处理发送失败
            }
            req.SendLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "发送", senddata, req.SendMemo);
            var PlanRevByteCount = req.PlanRevByteCount + 9;
            int Available = 0;
            for (var i = 0; i < mm.WaitTimes; i++)
            {
                var r = await SimWorker.MyDeay(mm.WaitMs);
                if (r != 0)
                {
                    req.Result = r;
                    return req.Result;
                }
                Available = this.Available();
                if (Available >= PlanRevByteCount)
                {
                    break;
                }
            }
            if (Available == 0)
            {
                req.Result = 3;
                req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", new byte[] { }, "超时");
                return req.Result;
            }
         
            if (Available <PlanRevByteCount)
            {
                var  data1=new byte[Available];
                socket.Receive(data1 );
                req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", data1, "超时");
                req.Result = 3;//超时
                return req.Result;
            }


            var revdata = new byte[Available];
            socket.Receive(revdata);

            req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", revdata, "应答："+req.SendMemo);
            if (revdata[8] < 10 && revdata.Count() > 20)
            {
                req.ReceiveLog.Memo += "*********";
            }

            if (revdata[0] == senddata[0] && revdata[1] == senddata[1])
            {
            }
            else
            {
                req.ReceiveLog.Memo = "流水号错误";
                req.Result = 4;//超时
                return req.Result;
            }


            if (revdata[6] == senddata[6] && revdata[7] == senddata[7])
            {
            }
            else
            {
                req.ReceiveLog.Memo = "校验失败";
                req.Result = 4;//超时
                return req.Result;
            }

            var bytenum = revdata[8];
            var data2 = new byte[bytenum];
            Buffer.BlockCopy(revdata, 9, data2,0, data2.Length);
            req.RevData= data2;
            if (req.ReqLen > 10 && req.RevData.Length < 6)
            {

            }
            req.Result = 0;
            return req.Result;

        }

        /// <summary>
        /// 发送数据  ，每个协议要跟进情况 加上 检验码 或者  流水号
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public override async Task<int> CmdAndRev(ProtocolSimHost mm, ReqAndRevVM req)
        {
             
            var senddata = GetCmdData(req);
            if (socket.Available > 0)
            {
                var datatmp = new byte[socket.Available];
                socket.Receive(datatmp);
            }
            socket.Send(senddata );
            req.SendLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "发送", senddata, req.SendMemo);
            var PlanRevByteCount = req.PlanRevByteCount + 6 ; //TCP头6加3
            int Available = 0;
            for (var i = 0; i < mm.WaitTimes; i++)
            {
                var r = await SimWorker.MyDeayForEnd(mm.WaitMs);
                if (r != 0)
                {
                    req.Result = r;
                    return req.Result;
                }
                Available = this.Available();
                if (Available >= PlanRevByteCount)
                {
                    break;
                }
            }
            if (Available == 0)
            {
                req.Result = 3;//超时
                return req.Result;
            }
            if (Available < PlanRevByteCount)
            {
                var data0 = new byte[Available];
                socket.Receive(data0);
                req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", data0, "超时");
                req.Result = 3;//超时
                return req.Result;
            }


            var revdata = new byte[Available];
            socket.Receive(revdata);
            req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", revdata, "应答：" + req.SendMemo);

            if (revdata[0] == senddata[0] && revdata[1] == senddata[1])
            {
            }
            else
            {
                req.ReceiveLog.Memo = "流水号错误";
                req.Result = 4;//超时
                return req.Result;
            }

            if (revdata[6] == senddata[6] && revdata[7] == senddata[7])
            {
            }
            else
            {
                req.ReceiveLog.Memo = "校验失败";
                req.Result = 4;//超时
                return req.Result;
            }

            var resultdata = new byte[revdata.Length - 8];
            Buffer.BlockCopy(revdata, 8, resultdata, 0, resultdata.Length);
            req.RevData = resultdata;
            req.Result = 0;
            return req.Result;
        }

    }
}
